package com.jweb.framework.core;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.Locale;
import java.util.Map;


import org.springframework.context.MessageSource;
import org.springframework.context.MessageSourceResolvable;
import org.springframework.context.NoSuchMessageException;
import org.springframework.validation.Errors;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;

import com.jweb.framework.core.channel.MessagesProvider;


public class DefaultMessagesProvider implements MessagesProvider {
	
	private MessageSource defaultMessageSource ;
	private MessageSource valuesMessageSource ;
	private MessageSource errorMessageSource ;
	private String defaultErrorKey  ;

	public void setDefaultMessageSource(MessageSource defaultMessageSource) {
		this.defaultMessageSource = defaultMessageSource;
	}

	public void setValuesMessageSource(MessageSource valuesMessageSource) {
		this.valuesMessageSource = valuesMessageSource;
	}

	public void setErrorMessageSource(MessageSource errorMessageSource) {
		this.errorMessageSource = errorMessageSource;
	}

	public void setDefaultErrorKey(String defaultErrorKey) {
		this.defaultErrorKey = defaultErrorKey;
	}

	public  Map getValues(String s, Locale locale) {
		return null ;
	}

	private String getValuesA(MessageSource messageSource,
			String str1, Object[] objs, Locale locale, String str2, String str3) {
		
		try {
			
			return messageSource.getMessage(str1, objs , locale); //"messageSource"=ReloadableResourceBundleMessageSource
			
		} catch (NoSuchMessageException e) {
			if(str2!=null);
			try {
				return messageSource.getMessage(str2, objs , locale);
			} catch (NoSuchMessageException e2) {
				if(str3!=null){
					return str3 ;
				}
				if(objs!=null && objs.length > 0){
					return str1+", with args : " + Arrays.asList(objs);
				}
			}
		}
		
		return str1 ;
	}

	public String getMessage(String s, Locale locale) {
		
		return getValuesA(this.defaultMessageSource, s, null, locale, null, s);
	}

	public String getMessage(String s, Object[] objs, Locale locale) {
		
		return getValuesA(this.defaultMessageSource, s, objs, locale, null, s);
	}

	

	public Object resolveError(Throwable throwable, Locale locale) {
		
		if(throwable instanceof CoreException && ((CoreException)throwable).isWrapped()){
			throwable = throwable.getCause();
		}
		
		Object obj = null ;
		if(throwable instanceof MessageSourceResolvable){
			obj = (MessageSourceResolvable)throwable ;
			return getValuesA(this.errorMessageSource, ((MessageSourceResolvable)obj).getCodes()[0], ((MessageSourceResolvable)obj).getArguments(), locale, this.defaultErrorKey, ((MessageSourceResolvable)obj).getDefaultMessage());
		}
		
		String str = throwable.getMessage();
		if(str!=null && str.length()>0){
			obj = getValuesA(this.errorMessageSource , str , null , locale);
		}
		if(obj!=null){
			return obj ;
		}
		str = throwable.getClass().getName();
		obj = getValuesA(this.errorMessageSource , str , null , locale);
		if(obj!=null){
			return obj ;
		}
		
		str = this.defaultErrorKey ;
		obj = getValuesA(this.errorMessageSource , str , null , locale);
		if(obj!=null){
			return obj ;
		}
		
		obj = throwable.getClass().getName()+(throwable.getMessage()!=null ? ":"+throwable.getMessage() : "");
		
		return obj ;
	}

	private Object getValuesA(MessageSource messageSource, String str,Object[] objs, Locale locale) {
		
		try {
			
			return messageSource.getMessage(str , objs , locale);
			
		} catch (NoSuchMessageException e) {
			
		}
		
		return null;
	}

	private Object resolveErrors(Errors errors, Locale locale) {
		
		LinkedHashMap linkedHashMap = new LinkedHashMap();
		for(ObjectError objectError : errors.getAllErrors()){
			Object obj = (objectError instanceof FieldError)?((FieldError)objectError).getField() : null ;
			String str = getValuesA(this.errorMessageSource , objectError , locale);
			linkedHashMap.put(obj, str);
		}
		
		return linkedHashMap ;
	}

	private String getValuesA(MessageSource messageSource, MessageSourceResolvable messageSourceResolvale , Locale locale) {
		
		try {
			
			return messageSource.getMessage(messageSourceResolvale, locale);
			
		} catch (NoSuchMessageException e) {
			if(messageSourceResolvale.getDefaultMessage()!=null){
				return messageSourceResolvale.getDefaultMessage();
			}
			if(messageSourceResolvale.getArguments()!=null && messageSourceResolvale.getArguments().length>0){
				return messageSourceResolvale.getCodes()[messageSourceResolvale.getCodes().length-1]+",with args:" + Arrays.asList(messageSourceResolvale.getArguments());
			}
		}
		
		return messageSourceResolvale.getCodes()[messageSourceResolvale.getCodes().length - 1];
	}

	public Object resolveError(String code , Object[] arg1, String arg2,
			Locale locale) {
		
		String str = (String) getValuesA(this.errorMessageSource , code , arg1 , locale);
		
		return (str == null) ? arg2 : str ;
	}

}
